import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.jgit.api.CloneCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.errors.UnsupportedCredentialItem;
import org.eclipse.jgit.transport.CredentialItem;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.JschConfigSessionFactory;
import org.eclipse.jgit.transport.SshSessionFactory;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.transport.OpenSshConfig.Host;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.jcraft.jsch.Session;

public class Implement implements Interface {

	
	@Override	
	public int userlogin(String username, String password) {
		// TODO Auto-generated method stub
		ConfigUtils a= new ConfigUtils();
		String ip = a.getIp();
		
		//加密密码
		String passwordwithMd5 = Md5Util.md5(password);
		URL url = null;
		try {
			url = new URL("http://"+ip+":8080/api/localApi/user/userValidate?username="+username+"&passwd="+passwordwithMd5);
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return 1;
			
		}
		//发起请求
		WebClient wb = new WebClient();
		WebRequest wbr = new WebRequest(url,HttpMethod.GET);
		Page page;
		try {
			page = wb.getPage(wbr);
		} catch (FailingHttpStatusCodeException | IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return 1;
			
		}
		
		//解析返回结果
		ObjectMapper mapper = new ObjectMapper();
		Map root = null;
		try {
			root = mapper.readValue(page.getWebResponse().getContentAsString(),Map.class);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return 1;
		}
		
		//code 0 成功 1 失败
		System.out.println(root.get("code"));
		System.out.println(root.get("results"));
		if(root.get("code").toString().equals("0")){
			return 0;
		}
		else{
			return 1;
		}
		
		wb.close();
	}

	@Override
	public int pullRepositoryByVersion(String username, String password,
			Long repositoryId, String projectAddress, String versionNum) {
		
		ConfigUtils a= new ConfigUtils();
		String ip = a.getIp();
		
		String remotepath = "ssh://root@"+ip+":22";
				
		URL url = null;
		try {
			url = new URL("http://"+ip+":8080/api/localApi/git/getRepo?repositoryId="+repositoryId);
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return 1;	
		}
		//发起请求
		WebClient wb = new WebClient();
		WebRequest wbr = new WebRequest(url,HttpMethod.GET);
		Page page;
		try {
			page = wb.getPage(wbr);
		} catch (FailingHttpStatusCodeException | IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return 1;
			
		}
		
		Gson gson = new Gson();
		JsonParser parser = new JsonParser();
		JsonElement  jel = parser.parse(page.getWebResponse().getContentAsString());
		
		JsonObject jsonObj = null;
		if(jel.isJsonObject()){
			System.out.println("jsonObject");
			jsonObj = jel.getAsJsonObject();  
			System.out.println(jsonObj.get("code").getAsString());
			if(jsonObj.get("code").getAsString().equals("0")){
				return 0;
			}
			else{
				return 1;
			}
			JsonElement  jel2 = jsonObj.get("results");
			JsonObject jobj = jel2.getAsJsonObject();
			System.out.println(jobj.get("name").getAsString());
			System.out.println(jobj.get("path").getAsString());
			System.out.println(jobj.get("repoId").getAsString());
			remotepath = remotepath+jobj.get("path").getAsString().trim()+jobj.get("name").getAsString().trim();
			
		}
		
		System.out.println(remotepath);
		SshSessionFactory.setInstance( new JschConfigSessionFactory() {
            @Override
            protected void configure( Host host, Session session ) {
              session.setPassword( "123456" );
            }
        } );
		
		if(userlogin(username,password)==0){
			
				//如果是仓库，pull
				if(isRepository(projectAddress)){
					File f = new File(projectAddress);
					try {
						Git git = Git.open(f);
						try {
							git.pull().call();
							git.close();
						} catch (GitAPIException e) {
							
							e.printStackTrace();
							//pull操作失败
							git.close();
							return 2;
						}
					} catch (IOException e) {
						
						e.printStackTrace();
						
						return 1;
					}
				}
				//如果不是仓库，clone
				else{
					File f = new File(projectAddress);
						if(f.exists()&&f.isDirectory()&&f.list().length==0){
							
						}else {
							deleteAllFilesOfDir(f);
							f.mkdirs();
						}
						
						 CloneCommand cc = new CloneCommand()
		                .setDirectory(f)
		                .setURI(remotepath);
						 try {
							Git git = cc.call();
							git.close();
						} catch (GitAPIException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
							return 3;
						}
						
				}
			}else{
				//用户登录失败
				return 1;
				
			}
//			
//			
//			
		wb.close();
		return 0;
	}

	@Override
	public List<Version> getRepositoryVersion(String username, String password,
			Long repositoryId) {
		
		List<Version> versions = new ArrayList<Version>();
		
		// TODO Auto-generated method stub
		if(userlogin(username,password)==0){
			ConfigUtils a= new ConfigUtils();
			String ip = a.getIp();
			
			//加密密码
			String passwordwithMd5 = Md5Util.md5(password);
			URL url = null;
			try {
				url = new URL("http://"+ip+":8080/api/localApi/git/getRepoVersions?repositoryId="+repositoryId);
			} catch (MalformedURLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return null;
				
			}
			//发起请求
			WebClient wb = new WebClient();
			WebRequest wbr = new WebRequest(url,HttpMethod.GET);
			Page page;
			try {
				page = wb.getPage(wbr);
			} catch (FailingHttpStatusCodeException | IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return null;
				
			}
			
			//解析返回结果
			
			Gson gson = new Gson();
			JsonParser parser = new JsonParser();
			JsonElement  jel = parser.parse(page.getWebResponse().getContentAsString());
			JsonArray jsonArray = null;
			
			JsonObject jsonObj = null;
			if(jel.isJsonObject()){
				System.out.println("jsonObject");
				jsonObj = jel.getAsJsonObject();  
				System.out.println(jsonObj.get("code").getAsString());
				if(!jsonObj.get("code").getAsString().equals("0")){
					return null;
				}
				JsonElement  jel2 = jsonObj.get("results");
				if(jel2.isJsonArray()){
					jsonArray = jel2.getAsJsonArray();
					Iterator it = jsonArray.iterator();
					while(it.hasNext()){
						JsonObject e = (JsonObject)it.next();
						
						String versionNum = e.get("verisonNum").getAsString().trim();
						versionNum = versionNum.substring(versionNum.lastIndexOf("/")+1);
						Version v = new Version(versionNum,e.get("remark").getAsString().trim());
						versions.add(v);
						
						System.out.println(versionNum);
						System.out.println(e.get("remark").getAsString().trim());
					}
				}
				
			}
			
			
			
		}
		wb.close();
		return versions;
	}

	@Override
	public boolean isRepository(String filepath) {
		// TODO Auto-generated method stub
		File f = new File(filepath);
		try {
			Git git = Git.open(f);
			return true;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
		
	}

	
	private static void deleteAllFilesOfDir(File path) {  
		if (!path.exists())  
	        return;  
	    if (path.isFile()) {  
	        path.delete();  
	        return;  
	    }  
	    File[] files = path.listFiles();  
	    for (int i = 0; i < files.length; i++) {  
	        deleteAllFilesOfDir(files[i]);  
	    }  
	    path.delete();  
	}  
	
	public List<Project> showRepository(String username, String password){

		List<Project> project = new ArrayList<Project>();
		
		
		// TODO Auto-generated method stub
		if(userlogin(username,password)==0){
			
			long userId = 0l;
			
			ConfigUtils a= new ConfigUtils();
			String ip = a.getIp();
			
			String passwordwithMd5 = Md5Util.md5(password);

			URL url5 = null;
			try {
				url5 = new URL("http://"+ip+":8080/api/localApi/user/login?username="+username+"&passwd="+passwordwithMd5);
			} catch (MalformedURLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return null;
				
			}
			//发起请求
			WebClient wb5 = new WebClient();
			WebRequest wbr5 = new WebRequest(url5,HttpMethod.GET);
			Page page5;
			try {
				page5 = wb5.getPage(wbr5);
			} catch (FailingHttpStatusCodeException | IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return null;
				
			}
			
			//解析返回结果
			Gson gson5 = new Gson();
			JsonParser parser5 = new JsonParser();
			JsonElement  jel5 = parser5.parse(page5.getWebResponse().getContentAsString());
			JsonArray jsonArray5 = null;									
			JsonObject jsonObj5 = null;
//			System.out.println(jel5.isJsonObject());
			if(jel5.isJsonObject()){
//				System.out.println("jsonObject");
				jsonObj5 = jel5.getAsJsonObject();  
//				System.out.println("code"+jsonObj5.get("code").getAsString());
				userId = jsonObj5.get("results").getAsLong();				
//				System.out.println("userId "+userId);
				
				
			}										
			
			URL url = null;
			try {
				url = new URL("http://"+ip+":8080/api/localApi/showRepository?userId="+userId);
			} catch (MalformedURLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return null;
				
			}
			//发起请求
			WebClient wb = new WebClient();
			WebRequest wbr = new WebRequest(url,HttpMethod.GET);
			Page page;
			try {
				page = wb.getPage(wbr);
			} catch (FailingHttpStatusCodeException | IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return null;
				
			}
			
			//解析返回结果
			Gson gson = new Gson();
			JsonParser parser = new JsonParser();
			JsonElement  jel = parser.parse(page.getWebResponse().getContentAsString());
			JsonArray jsonArray = null;									
			JsonObject jsonObj = null;
			if(jel.isJsonObject()){
//				System.out.println("jsonObject");
				jsonObj = jel.getAsJsonObject();  
//				System.out.println("code"+jsonObj.get("code").getAsString());
				JsonElement  jel2 = jsonObj.get("results");
				if(jel2.isJsonArray()){
					jsonArray = jel2.getAsJsonArray();
					Iterator it = jsonArray.iterator();
					while(it.hasNext()){
						JsonObject e = (JsonObject)it.next();
						
						ArrayList<GitVM> gitlist = new ArrayList<GitVM>();
						
						Long projectId = e.get("projectId").getAsLong();
						String name = e.get("name").getAsString().trim();
						Integer status = e.get("status").getAsInt();
						String desc = e.get("desc").getAsString().trim();
						String time = e.get("time").getAsString().trim();
						
//						JsonElement time = e.get("time");						
//						System.out.println("time "+e.get("time"));
						
						JsonElement  jel3 = e.get("repository");
						if(jel3.isJsonArray()){
							JsonArray jsonArray1 = jel3.getAsJsonArray();
							Iterator it1 = jsonArray1.iterator();
							while(it1.hasNext()){
								JsonObject e1 = (JsonObject)it1.next();								
								Long repoId = e1.get("repoId").getAsLong();
								String name1 = e1.get("name").getAsString().trim();
								String path = e1.get("path").getAsString().trim();								
								GitVM vm = new GitVM(repoId, name1, path);								
								gitlist.add(vm);
																								
							}
						}												
//						Gson gson1 = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();						
//						Date time1 = gson1.fromJson(time, Date.class);						
//						System.out.println("time1 "+time1);  						
//						System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time1));  						
						SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");				

						try{
							Project p = new Project(projectId, gitlist, name, status, desc, sdf.parse(time));
							project.add(p);	
							
						}catch(ParseException e1){
							e1.printStackTrace();
							return null;
							
						}

																							
					}
				}				
			}									
		}
		return project;
	}

	@Override
	public int pushMethod(String username, String password, List<String> repositoryAddressList, String remark) {
		// TODO Auto-generated method stub
		ConfigUtils a= new ConfigUtils();
		String ip = a.getIp();			

		int sum = 0;

		int flag = 0;
		
		
		if(userlogin(username,password)==0){
			
			SshSessionFactory.setInstance( new JschConfigSessionFactory() {
	            @Override
	            protected void configure( Host host, Session session ) {
	              session.setPassword( "123456" );
	            }
	        } );
			
			for(int i = 0;i<repositoryAddressList.size();i++){								
												
				flag = 1;
				try (Git git = Git.open(new File(repositoryAddressList.get(i)))) {
	                try {
						git.add()
						        .addFilepattern(".")
						        .call();
					} catch (GitAPIException e2) {
						// TODO Auto-generated catch block
						e2.printStackTrace();
						flag = 0;
					}

	                try {
						git.commit()                        
						        .setMessage(remark)
						        .call();
					} catch (GitAPIException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
						flag = 0;
					}
	                CredentialsProvider allowHosts = new CredentialsProvider() {

	                    @Override
	                    public boolean supports(CredentialItem... items) {
	                        for(CredentialItem item : items) {
	                            if((item instanceof CredentialItem.YesNoType)) {
	                                return true;
	                            }
	                        }
	                        return false;
	                    }

	                    @Override
	                    public boolean get(URIish uri, CredentialItem... items) throws UnsupportedCredentialItem {
	                        for(CredentialItem item : items) {
	                            if(item instanceof CredentialItem.YesNoType) {
	                                ((CredentialItem.YesNoType)item).setValue(true);
	                                return true;
	                            }
	                        }
	                        return false;
	                    }

	                    @Override
	                    public boolean isInteractive() {
	                        return false;
	                    }
	                };
	                try {
						git.push()
						.setCredentialsProvider(allowHosts)
						.call();
					} catch (GitAPIException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
						flag = 0;
					}

//	                System.out.println("push success" );
	                flag = 1;
	            } catch (IOException e3) {
					// TODO Auto-generated catch block
					e3.printStackTrace();
					flag = 0;
				}							
					sum =sum + flag;
				}			
			}										
		if(sum == repositoryAddressList.size()){			
			flag = 0;
		}else{			
			flag = 1;
		}
		
		return flag;
	}

	@Override
	public int pullMethod(String username, String password, String projectAddress, List<Long> repositoryIdList) {
		// TODO Auto-generated method stub
		ConfigUtils a= new ConfigUtils();
		String ip = a.getIp();
		
		int flag = 0;			
		String name1 = null;
		String path = null;
		if(userlogin(username,password)==0){
			
			SshSessionFactory.setInstance( new JschConfigSessionFactory() {
	            @Override
	            protected void configure( Host host, Session session ) {
	              session.setPassword( "123456" );
	            }
	        } );
			
			for(int i = 0;i<repositoryIdList.size();i++){				
//				System.out.println(repositoryIdList.get(i));				
				URL url1 = null;
				try {
					url1 = new URL("http://"+ip+":8080/api/localApi/getRepoById?repoId="+repositoryIdList.get(i));
				} catch (MalformedURLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					flag = 1;
					return flag;
				}
				//发起请求
				WebClient wb1 = new WebClient();
				WebRequest wbr1 = new WebRequest(url1,HttpMethod.GET);
				Page page1;
				try {
					page1 = wb1.getPage(wbr1);
				} catch (FailingHttpStatusCodeException | IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					flag = 1;
					return flag;
				}
				
				Gson gson1 = new Gson();
				JsonParser parser1 = new JsonParser();
				JsonElement  jel1 = parser1.parse(page1.getWebResponse().getContentAsString());
				JsonArray jsonArray1 = null;
				JsonObject jsonObj1 = null;
				if(jel1.isJsonObject()){
//					System.out.println("jsonObject");
					jsonObj1 = jel1.getAsJsonObject();  
//					System.out.println(jsonObj1.get("code").getAsString());
					JsonElement  jel2 = jsonObj1.get("results");
//					System.out.println("jel2isJsonObject() "+jel2.isJsonObject());
					if(jel2.isJsonObject()){
						
						JsonObject jsob = jel2.getAsJsonObject();
						Long repoId = jsob.get("repoId").getAsLong();
						name1 = jsob.get("name").getAsString();
						path = jsob.get("path").getAsString().trim();
						
					}
				}										
//				System.out.println(name1);													
				if(!(new File(projectAddress+name1).exists())){
					
					
					String remotepath = "ssh://root@"+ip+":22";
//					System.out.println("clone");
					 CredentialsProvider allowHosts = new CredentialsProvider() {

				            @Override
				            public boolean supports(CredentialItem... items) {
				                for(CredentialItem item : items) {
				                    if((item instanceof CredentialItem.YesNoType)) {
				                        return true;
				                    }
				                }
				                return false;
				            }

				            @Override
				            public boolean get(URIish uri, CredentialItem... items) throws UnsupportedCredentialItem {
				                for(CredentialItem item : items) {
				                    if(item instanceof CredentialItem.YesNoType) {
				                        ((CredentialItem.YesNoType)item).setValue(true);
				                        return true;
				                    }
				                }
				                return false;
				            }

				            @Override
				            public boolean isInteractive() {
				                return false;
				            }
				        };
				        			     

				        File localpath = new File(projectAddress+name1);
				    	try {
							localpath.createNewFile();
						} catch (IOException e1) {
							// TODO Auto-generated catch block
							e1.printStackTrace();
							flag = 1;
						}
				        localpath.delete();

				        // then clone
//				        System.out.println("Cloning from " + url + " to " + localpath);
				        try (Git result = Git.cloneRepository()
				                .setURI(remotepath+path+name1)
				                .setDirectory(localpath)
				                .setCredentialsProvider(allowHosts)
				                .call()) {
					        // Note: the call() returns an opened repository already which needs to be closed to avoid file handle leaks!
//					        System.out.println("Having repository: " + result.getRepository().getDirectory());
					        
				        }catch(Exception e){
				        	e.printStackTrace();
							flag = 1;
				        }
				        
				}else{
//					System.out.println("pull");
					 CredentialsProvider allowHosts = new CredentialsProvider() {

				            @Override
				            public boolean supports(CredentialItem... items) {
				                for(CredentialItem item : items) {
				                    if((item instanceof CredentialItem.YesNoType)) {
				                        return true;
				                    }
				                }
				                return false;
				            }

				            @Override
				            public boolean get(URIish uri, CredentialItem... items) throws UnsupportedCredentialItem {
				                for(CredentialItem item : items) {
				                    if(item instanceof CredentialItem.YesNoType) {
				                        ((CredentialItem.YesNoType)item).setValue(true);
				                        return true;
				                    }
				                }
				                return false;
				            }

				            @Override
				            public boolean isInteractive() {
				                return false;
				            }
				        };

				        File localpath = new File(projectAddress+name1);	        
				        try {
							Git git = Git.open(localpath);
							try {
								git.pull().setCredentialsProvider(allowHosts).call();
								
//								System.out.println("Pulled from remote repository to local repository at " + git.getRepository().getDirectory());
								git.close();
							} catch (GitAPIException e) {
								
								e.printStackTrace();
								//pull操作失败
								git.close();
								flag =1;
							}
						} catch (IOException e) {
							
							e.printStackTrace();
							flag =1;
						}	        																	
				}																																				
			}									
		}
		return flag;	
	}
	
}
